package com.yanqu.road.dao.impl.channelcenter.washe;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dao.impl.TempDataObjectDao;
import com.yanqu.road.entity.activity.washe.data.WasheBoxData;
import com.yanqu.road.entity.activity.washe.data.WasheRmbMallData;
import com.yanqu.road.entity.activity.washe.data.WasheUserData;
import com.yanqu.road.utils.string.StringUtils;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WasheUserDataDaoImpl extends TempDataObjectDao<WasheUserData> {

    public static String getWasheUserDataSql = "select * from `t_u_washe_user` where `userId`=?";

    public WasheUserData getWasheUserData(long userId) {
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getUserDb());
            call = getDb().getConnection().prepareCall(getWasheUserDataSql);
            int i = 1;
            call.setLong(i++, userId);
            rs = call.executeQuery();
            if (rs.next()) {
                return parse(rs);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return null;
    }

    public static String updateWasheUserDataSql = "update `t_u_washe_user` set score=?,unlockCard=?,unlockSkill=?,seasonScoreMap=?,seasonTopScoreMap=?,buffTimes=?,buffCollectTimes=?,silverSet=?,goldSet=?,boxDataList=?,dataSeason=?,inGameMomentList=?,guide=?,playTimes=?,continueFailTimes=?,rmbMallMap=?,seasonPlayTime=?,todayPlayTime=?,dayResetTime=?,dayPlayTimes=?,daySurrenderTimes=?,continueWinTimes=?,selectedSkill=?,shareRewardTime=?,linkGuide=?,decorationMap=? where userId=?";

    @Override
    protected boolean updateData(WasheUserData washeUserData) {
        washeUserData.setBeginWriteTime();
        getDb().setConnName(DbNameStrategy.getUserDb());
        int i = 1;
        Map<Integer, DbParameter> para = new HashMap<Integer, DbParameter>();
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getScore()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getUnlockCard())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getUnlockSkill())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSeasonScoreMap())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSeasonTopScoreMap())));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getBuffTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getBuffCollectTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSilverSet())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getGoldSet())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getBoxDataList())));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDataSeason()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getMemorySeeList())));
        para.put(i++, new DbParameter(Types.BOOLEAN, washeUserData.isGuide()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getPlayTimes()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getContinueFailTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getRmbMallMap())));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getSeasonPlayTime()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getTodayPlayTime()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getDayResetTime()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDayPlayTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDaySurrenderTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getContinueWinTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSelectedSkill())));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getShareRewardTime()));
        para.put(i++, new DbParameter(Types.BOOLEAN, washeUserData.isLinkGuide()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getDecorationMap())));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getUserId()));
        if (getDb().executeNoneQuery(updateWasheUserDataSql, para) > 0) {
            return true;
        }
        return false;
    }

    public static String insertWasheUserDataSql = "insert into `t_u_washe_user`(userId,score,unlockCard,unlockSkill,seasonScoreMap,seasonTopScoreMap,buffTimes,buffCollectTimes,silverSet,goldSet,boxDataList,dataSeason,inGameMomentList,guide,playTimes,continueFailTimes,rmbMallMap,seasonPlayTime,todayPlayTime,dayResetTime,dayPlayTimes,daySurrenderTimes,continueWinTimes,selectedSkill,shareRewardTime,linkGuide,decorationMap) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    @Override
    protected boolean addData(WasheUserData washeUserData) {
        washeUserData.setBeginWriteTime();
        getDb().setConnName(DbNameStrategy.getUserDb());
        int i = 1;
        Map<Integer, DbParameter> para = new HashMap<Integer, DbParameter>();
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getUserId()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getScore()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getUnlockCard())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getUnlockSkill())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSeasonScoreMap())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSeasonTopScoreMap())));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getBuffTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getBuffCollectTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSilverSet())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getGoldSet())));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getBoxDataList())));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDataSeason()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getMemorySeeList())));
        para.put(i++, new DbParameter(Types.BOOLEAN, washeUserData.isGuide()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getPlayTimes()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getContinueFailTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getRmbMallMap())));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getSeasonPlayTime()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getTodayPlayTime()));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getDayResetTime()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDayPlayTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getDaySurrenderTimes()));
        para.put(i++, new DbParameter(Types.INTEGER, washeUserData.getContinueWinTimes()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getSelectedSkill())));
        para.put(i++, new DbParameter(Types.BIGINT, washeUserData.getShareRewardTime()));
        para.put(i++, new DbParameter(Types.BOOLEAN, washeUserData.isLinkGuide()));
        para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(washeUserData.getDecorationMap())));
        if (getDb().executeNoneQuery(insertWasheUserDataSql, para) > 0) {
            return true;
        }
        return false;
    }

    @Override
    protected WasheUserData parseData(ResultSet rs) throws SQLException {
        WasheUserData washeUserData = new WasheUserData();
        washeUserData.setUserId(rs.getLong("userId"));
        washeUserData.setScore(rs.getLong("score"));
        washeUserData.setUnlockCard(JSON.parseObject(rs.getString("unlockCard"), new TypeReference<HashSet<Integer>>() {
        }));
        washeUserData.setUnlockSkill(JSON.parseObject(rs.getString("unlockSkill"), new TypeReference<HashSet<Integer>>() {
        }));
        washeUserData.setSeasonScoreMap(JSON.parseObject(rs.getString("seasonScoreMap"), new TypeReference<ConcurrentHashMap<Integer, Long>>() {
        }));
        washeUserData.setSeasonTopScoreMap(JSON.parseObject(rs.getString("seasonTopScoreMap"), new TypeReference<ConcurrentHashMap<Integer, Long>>() {
        }));
        washeUserData.setBuffTimes(rs.getInt("buffTimes"));
        washeUserData.setBuffCollectTimes(rs.getInt("buffCollectTimes"));
        washeUserData.setSilverSet(JSON.parseObject(rs.getString("silverSet"), new TypeReference<HashSet<Integer>>() {
        }));
        washeUserData.setGoldSet(JSON.parseObject(rs.getString("goldSet"), new TypeReference<HashSet<Integer>>() {
        }));
        washeUserData.setBoxDataList(JSON.parseObject(rs.getString("boxDataList"), new TypeReference<List<WasheBoxData>>() {
        }));
        washeUserData.setDataSeason(rs.getInt("dataSeason"));
        String inGameMomentList = rs.getString("inGameMomentList");
        if (!StringUtils.isNullOrEmpty(inGameMomentList)) {
            washeUserData.setMemorySeeList(JSON.parseObject(inGameMomentList, new TypeReference<List<Integer>>() {
            }));
        }
        washeUserData.setGuide(rs.getBoolean("guide"));
        washeUserData.setPlayTimes(rs.getLong("playTimes"));
        washeUserData.setContinueFailTimes(rs.getLong("continueFailTimes"));
        washeUserData.setRmbMallMap(JSON.parseObject(rs.getString("rmbMallMap"), new TypeReference<ConcurrentHashMap<Integer, WasheRmbMallData>>() {
        }));
        washeUserData.setSeasonPlayTime(rs.getLong("seasonPlayTime"));
        washeUserData.setTodayPlayTime(rs.getLong("todayPlayTime"));
        washeUserData.setDayResetTime(rs.getLong("dayResetTime"));
        washeUserData.setDayPlayTimes(rs.getInt("dayPlayTimes"));
        washeUserData.setDaySurrenderTimes(rs.getInt("daySurrenderTimes"));
        washeUserData.setContinueWinTimes(rs.getInt("continueWinTimes"));
        String selectedSkill = rs.getString("selectedSkill");
        if (!StringUtils.isNullOrEmpty(selectedSkill)) {
            washeUserData.setSelectedSkill(JSON.parseObject(selectedSkill, new TypeReference<List<Integer>>() {
            }));
        }
        washeUserData.setShareRewardTime(rs.getLong("shareRewardTime"));
        washeUserData.setLinkGuide(rs.getBoolean("linkGuide"));
        String decorationMap = rs.getString("decorationMap");
        if (decorationMap == null){
            washeUserData.setDecorationMap(new ConcurrentHashMap<>());
            washeUserData.setUpdateOption();
        }else {
            washeUserData.setDecorationMap(JSON.parseObject(decorationMap, new TypeReference<ConcurrentHashMap<Integer, Integer>>() {}));
        }

        return washeUserData;
    }

    // ---------------------------------------------

    public Map<Long, WasheUserData> getWasheUserDataMapByDataSeason(int minDataSeason) {
        Map<Long, WasheUserData> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        String sql = "select * from `t_u_washe_user` where `dataSeason`>=?";
        try {
            getDb().setConnName(DbNameStrategy.getUserDb());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++, minDataSeason);
            rs = call.executeQuery();
            while (rs.next()) {
                WasheUserData userData = parse(rs);
                map.put(userData.getUserId(), userData);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return map;
    }

}
